home *** CD-ROM | disk | FTP | other *** search
- /* Implements an elisp-programmable menubar.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
- Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "device.h"
- #include "frame.h"
- #include "redisplay.h"
- #include "window.h"
-
- int menubar_show_keybindings;
- Lisp_Object Vmenubar_configuration;
-
- Lisp_Object Qcurrent_menubar;
- Lisp_Object Qmenu_no_selection_hook;
-
- Lisp_Object Q_active, Q_suffix, Q_keys, Q_style, Q_selected;
- Lisp_Object Q_filter, Q_config, Q_included;
- Lisp_Object Qtoggle, Qradio, Qbutton;
-
- Lisp_Object Qactivate_menubar_hook, Vactivate_menubar_hook;
-
- Lisp_Object Vmenubar_visible_p;
-
- /* #### This function should disappear. Replace `current-menubar'
- with a specifier. */
- DEFUN ("set-menubar-dirty-flag", Fset_menubar_dirty_flag,
- Sset_menubar_dirty_flag, 0, 0, 0,
- "Tell XEmacs that the menubar has to be updated.")
- ()
- {
- MARK_MENUBAR_CHANGED;
- return Qnil;
- }
-
- void
- update_frame_menubars (struct frame *f)
- {
- struct device *d = XDEVICE (f->device);
-
- if (f->menubar_changed || f->windows_changed)
- MAYBE_DEVMETH (d, update_frame_menubars, (f));
-
- f->menubar_changed = 0;
- }
-
- static void
- menubar_visible_p_changed (Lisp_Object specifier, struct window *w,
- Lisp_Object oldval)
- {
- Fset_menubar_dirty_flag ();
- }
-
- void
- syms_of_menubar (void)
- {
- defkeyword (&Q_active, ":active");
- defkeyword (&Q_suffix, ":suffix");
- defkeyword (&Q_keys, ":keys");
- defkeyword (&Q_style, ":style");
- defkeyword (&Q_selected, ":selected");
- defkeyword (&Q_filter, ":filter");
- defkeyword (&Q_config, ":config");
- defkeyword (&Q_included, ":included");
-
- defsymbol (&Qtoggle, "toggle");
- defsymbol (&Qradio, "radio");
- defsymbol (&Qbutton, "button");
-
- defsymbol (&Qmenu_no_selection_hook, "menu-no-selection-hook");
- defsymbol (&Qcurrent_menubar, "current-menubar");
-
- defsubr (&Sset_menubar_dirty_flag);
- }
-
- void
- vars_of_menubar (void)
- {
- /* #### Replace current menubar with a specifier. */
- /*
- *
- * This DEFVAR_LISP is just for the benefit of make-docfile. there is no
- * C variable Vcurrent_menubar - all C code must access the menubar via
- * Qcurrent_menubar because it can be buffer-local.
- *
-
- DEFVAR_LISP ("current-menubar", &Vcurrent_menubar,
- "The current menubar. This may be buffer-local.\n\
- \n\
- When the menubar is changed, the function `set-menubar-dirty-flag' has to\n\
- be called for the menubar to be updated on the frame. See `set-menubar'\n\
- and `set-buffer-menubar'.\n\
- \n\
- A menubar is a list of menus and menu-items.\n\
- A menu is a list of menu items, keyword-value pairs, strings, and submenus.\n\
- \n\
- The first element of a menu must be a string, which is the name of the menu.\n\
- This is the string that will be displayed in the parent menu, if any. For\n\
- toplevel menus, it is ignored. This string is not displayed in the menu\n\
- itself.\n\
- \n\
- Immediately following the name string of the menu, any of three\n\
- optional keyword-value pairs is permitted.\n\
- \n\
- If an element of a menu (or menubar) is a string, then that string will be\n\
- presented as unselectable text.\n\
- \n\
- If an element of a menu is a string consisting solely of hyphens, then that\n\
- item will be presented as a solid horizontal line.\n\
- \n\
- If an element of a menu is a list, it is treated as a submenu. The name of\n\
- that submenu (the first element in the list) will be used as the name of the\n\
- item representing this menu on the parent.\n\
- \n\
- If an element of a menubar is `nil', then it is used to represent the\n\
- division between the set of menubar-items which are flushleft and those\n\
- which are flushright.\n\
- \n\
- Otherwise, the element must be a vector, which describes a menu item.\n\
- A menu item can have any of the following forms:\n\
- \n\
- [ \"name\" callback <active-p> ]\n\
- [ \"name\" callback <active-p> \"suffix\" ]\n\
- [ \"name\" callback :<keyword> <value> :<keyword> <value> ... ]\n\
- \n\
- The name is the string to display on the menu; it is filtered through the\n\
- resource database, so it is possible for resources to override what string\n\
- is actually displayed.\n\
- \n\
- If the `callback' of a menu item is a symbol, then it must name a command.\n\
- It will be invoked with `call-interactively'. If it is a list, then it is\n\
- evaluated with `eval'.\n\
- \n\
- The possible keywords are this:\n\
- \n\
- :active <form> Same as <active-p> in the first two forms: the\n\
- expression is evaluated just before the menu is\n\
- displayed, and the menu will be selectable only if\n\
- the result is non-nil.\n\
- \n\
- :suffix \"string\" Same as \"suffix\" in the second form: the suffix is\n\
- appended to the displayed name, providing a convenient\n\
- way of adding the name of a command's ``argument'' to\n\
- the menu, like ``Kill Buffer NAME''.\n\
- \n\
- :keys \"string\" Normally, the keyboard equivalents of commands in\n\
- menus are displayed when the `callback' is a symbol.\n\
- This can be used to specify keys for more complex menu\n\
- items. It is passed through `substitute-command-keys'\n\
- first.\n\
- \n\
- :style <style> Specifies what kind of object this menu item is:\n\
- \n\
- nil A normal menu item.\n\
- toggle A toggle button.\n\
- radio A radio button.\n\
- button A menubar button.\n\
- \n\
- The only difference between toggle and radio buttons is\n\
- how they are displayed. But for consistency, a toggle\n\
- button should be used when there is one option whose\n\
- value can be turned on or off, and radio buttons should\n\
- be used when there is a set of mutally exclusive\n\
- options. When using a group of radio buttons, you\n\
- should arrange for no more than one to be marked as\n\
- selected at a time.\n\
- \n\
- :selected <form> Meaningful only when STYLE is `toggle', `radio' or\n\
- `button'. This specifies whether the button will be in\n\
- the selected or unselected state.\n\
- \n\
- :included <form> This can be used to control the visibility of a menu or\n\
- menu item. The form is evaluated and the menu or menu\n\
- item is only displayed if the result is non-nil.\n\
- \n\
- :config <symbol> This is an efficient shorthand for\n\
- :included (memq symbol menubar-configuration)\n\
- See the variable `menubar-configuration'.\n\
- \n\
- :filter <function> A menu filter can only be used in a menu item list.\n\
- (i.e.: not in a menu item itself). It is used to\n\
- sensitize or incrementally create a submenu only when\n\
- it is selected by the user and not every time the\n\
- menubar is activated. The filter function is passed\n\
- the list of menu items in the submenu and must return a\n\
- list of menu items to be used for the menu. It is\n\
- called only when the menu is about to be displayed, so\n\
- other menus may already be displayed. Vile and\n\
- terrible things will happen if a menu filter function\n\
- changes the current buffer, window, or frame. It\n\
- also should not raise, lower, or iconify any frames.\n\
- Basically, the filter function should have no\n\
- side-effects.\n\
- \n\
- For example:\n\
- \n\
- (\"File\"\n\
- :filter file-menu-filter ; file-menu-filter is a function that takes\n\
- ; one argument (a list of menu items) and\n\
- ; returns a list of menu items\n\
- [ \"Save As...\" write-file t ]\n\
- [ \"Revert Buffer\" revert-buffer (buffer-modified-p) ]\n\
- [ \"Read Only\" toggle-read-only :style toggle\n\
- :selected buffer-read-only ]\n\
- )\n\
- \n\
- See x-menubar.el for many more examples.\n\
- \n\
- After the menubar is clicked upon, but before any menus are popped up,\n\
- the functions on the `activate-menubar-hook' are invoked to make top-level\n\
- changes to the menus and menubar. Note, however, that the use of menu\n\
- filters (using the :filter keyword) is usually a more efficient way to\n\
- dynamically alter or sensitize menus.");
- */
-
- Fset (Qcurrent_menubar, Qnil);
-
- DEFVAR_LISP ("activate-menubar-hook", &Vactivate_menubar_hook,
- "Function or functions called before a menubar menu is pulled down.\n\
- These functions are called with no arguments, and should interrogate and\n\
- modify the value of `current-menubar' as desired.\n\
- \n\
- The functions on this hook are invoked after the mouse goes down, but before\n\
- the menu is mapped, and may be used to activate, deactivate, add, or delete\n\
- items from the menus. However, it is probably the case that using a :filter\n\
- keyword in a submenu would be a more efficient way of updating menus. See\n\
- the documentation of `current-menubar'.\n\
- \n\
- These functions may return the symbol `t' to assert that they have made\n\
- no changes to the menubar. If any other value is returned, the menubar is\n\
- recomputed. If `t' is returned but the menubar has been changed, then the\n\
- changes may not show up right away. Returning `nil' when the menubar has\n\
- not changed is not so bad; more computation will be done, but redisplay of\n\
- the menubar will still be performed optimally.");
- Vactivate_menubar_hook = Qnil;
- defsymbol (&Qactivate_menubar_hook, "activate-menubar-hook");
-
- /*
- * This DEFVAR_LISP is just for the benefit of make-docfile.
- DEFVAR_LISP ("menu-no-selection-hook", &Vmenu_no_selection_hook,
- "Function or functions to call when a menu or dialog box is dismissed\n\
- without a selection having been made.");
- */
- Fset (Qmenu_no_selection_hook, Qnil);
-
- DEFVAR_BOOL ("menubar-show-keybindings", &menubar_show_keybindings,
- "If true, the menubar will display keyboard equivalents.\n\
- If false, only the command names will be displayed.");
- menubar_show_keybindings = 1;
-
- DEFVAR_LISP ("menubar-configuration", &Vmenubar_configuration,
- "A list of symbols, against which the value of the :config tag for each\n\
- menubar item will be compared. If a menubar item has a :config tag, then\n\
- it is omitted from the menubar if that tag is not a member of the\n\
- `menubar-configuration' list.");
- Vmenubar_configuration = Qnil;
- }
-
- void
- specifier_vars_of_menubar (void)
- {
- DEFVAR_SPECIFIER ("menubar-visible-p", &Vmenubar_visible_p,
- "*Whether the menubar is visible.\n\
- This is a specifier; use `set-specifier' to change it.");
- Vmenubar_visible_p = Fmake_specifier (Qboolean);
-
- set_specifier_fallback (Vmenubar_visible_p, list1 (Fcons (Qnil, Qt)));
- set_specifier_caching (Vmenubar_visible_p,
- slot_offset (struct window,
- menubar_visible_p),
- menubar_visible_p_changed,
- 0, 0);
- }
-